Skip to content

Insulate bitcoin-ohttp and bitcoin-hpke from the public API#1702

Draft
spacebear21 wants to merge 2 commits into
payjoin:masterfrom
spacebear21:api/insulate-ohttp-hpke
Draft

Insulate bitcoin-ohttp and bitcoin-hpke from the public API#1702
spacebear21 wants to merge 2 commits into
payjoin:masterfrom
spacebear21:api/insulate-ohttp-hpke

Conversation

@spacebear21

Copy link
Copy Markdown
Collaborator

Summary

Part of the 1.0 API hardening: remove pre-1.0 foreign crate types
(bitcoin-ohttp 0.6, bitcoin-hpke 0.13) from payjoin's public API so that a
breaking release of either dependency no longer forces a breaking release of
payjoin. The rust-bitcoin 0.32 and bitcoin_uri 0.1 pins are intentionally kept
for 1.0.

bitcoin-hpke

Make the inner tuple fields of HpkeSecretKey and HpkePublicKey private and
drop their Deref impls, so the wrapped secp256k1/hpke KEM key types are no
longer reachable through the public API. Callers use the existing accessors and
to_/from_compressed_bytes.

bitcoin-ohttp

  • OhttpKeys' inner ohttp::KeyConfig field is now private and the
    Deref/DerefMut impls are removed.
  • OhttpKeys::decode/encode/to_bytes/TryFrom return a new opaque
    OhttpKeysError instead of ohttp::Error (the foreign error is erased
    behind Box<dyn Error + Send + Sync>, keeping the source() chain).
  • The v2 create_*/process_* methods now return/accept a new opaque
    OhttpResponse newtype instead of ohttp::ClientResponse.
  • ohttp_encapsulate takes &OhttpKeys directly.

payjoin-cli and payjoin-ffi are updated to the new API. The FFI's exported
uniffi surface is unchanged (only its internal plumbing types), so the language
bindings do not require regeneration.

The two changes are split into separate commits (hpke, then ohttp) for review.

Disclosure: co-authored by Claude Code (Opus 4.8)

🤖 Generated with Claude Code

HpkeSecretKey and HpkePublicKey each wrapped a bitcoin-hpke KEM key
type behind a public tuple field plus a Deref impl, leaking those
foreign types into payjoin's public API. A breaking release of
bitcoin-hpke would then force a breaking release of payjoin.

Make the inner fields private and drop the Deref impls so the foreign
key types are no longer reachable through the public API. Callers use
the existing accessor methods and to_/from_compressed_bytes, so no
downstream code changes are required.
Several bitcoin-ohttp types leaked into payjoin's public API: OhttpKeys
exposed its inner ohttp::KeyConfig through a public field and Deref,
decode/to_bytes returned ohttp::Error, and ohttp::ClientResponse
appeared directly in the v2 create_*/process_* signatures. A breaking
release of bitcoin-ohttp would then force a breaking release of payjoin.

Make the OhttpKeys field private and drop its Deref/DerefMut, wrap the
key config error in a new OhttpKeysError that erases ohttp::Error, and
return the OHTTP response context as a new opaque OhttpResponse newtype.
ohttp_encapsulate now takes &OhttpKeys directly.

Tests build OhttpKeys through the public decode API via a new
payjoin_test_utils::ohttp_key_config_bytes helper (plus ohttp_server for
the emulated gateway), since production code only ever constructs
OhttpKeys from directory bytes.
@coveralls

Copy link
Copy Markdown
Collaborator

Coverage Report for CI Build 28557993858

Coverage increased (+0.04%) to 85.781%

Details

  • Coverage increased (+0.04%) from the base build.
  • Patch coverage: 3 uncovered changes across 1 file (63 of 66 lines covered, 95.45%).
  • No coverage regressions found.

Uncovered Changes

File Changed Covered %
payjoin/src/core/ohttp.rs 21 18 85.71%
Total (7 files) 66 63 95.45%

Coverage Regressions

No coverage regressions found.


Coverage Stats

Coverage Status
Relevant Lines: 15317
Covered Lines: 13139
Line Coverage: 85.78%
Coverage Strength: 355.7 hits per line

💛 - Coveralls

@DanGould

DanGould commented Jul 2, 2026

Copy link
Copy Markdown
Member

concept ACK this is important before 1.0-rc.4

@benalleng

Copy link
Copy Markdown
Collaborator

We either need to remove ohttp as a direct dep in the ffi or add it to the machete ignore
https://github.com/spacebear21/rust-payjoin/blob/09280677f3d766f09ef4035fac730fd152f2d76c/payjoin-ffi/Cargo.toml#L42-L45

2026-07-02T01:09:08.8952465Z error: Cannot build '/nix/store/f0fhx35c3p329xwryaf4904ra9qgr95k-payjoin-workspace-machete-no-version.drv'.
2026-07-02T01:09:08.8956169Z        Reason: builder failed with exit code 1.
2026-07-02T01:09:08.8957125Z        Output paths:
2026-07-02T01:09:08.8958319Z          /nix/store/b27khb70d8d98yn7x80h2lkn3anlw0sx-payjoin-workspace-machete-no-version
2026-07-02T01:09:08.8959514Z        Last 25 log lines:
2026-07-02T01:09:08.8960237Z        > Running phase: configurePhase
2026-07-02T01:09:08.8961935Z        > will append /build/source/.cargo-home/config.toml with contents of /nix/store/hxgfjjmzqzfp75asv5dqibxycc8hc8nd-vendor-cargo-deps/config.toml
2026-07-02T01:09:08.8963478Z        > default configurePhase, nothing to do
2026-07-02T01:09:08.8964249Z        > Running phase: buildPhase
2026-07-02T01:09:08.8964976Z        > +++ command cargo --version
2026-07-02T01:09:08.8965742Z        > cargo 1.98.0-nightly (a335d47ff 2026-06-26)
2026-07-02T01:09:08.8966543Z        > Running phase: checkPhase
2026-07-02T01:09:08.8967257Z        > +++ command cargo machete
2026-07-02T01:09:08.8968049Z        > Analyzing dependencies of crates in this directory...
2026-07-02T01:09:08.8969116Z        > cargo-machete found the following unused dependencies in this directory:
2026-07-02T01:09:08.8970146Z        > payjoin-ffi -- ./payjoin-ffi/Cargo.toml:
2026-07-02T01:09:08.8971287Z        >         ohttp
2026-07-02T01:09:08.8971922Z        >
2026-07-02T01:09:08.8972753Z        > If you believe cargo-machete has detected an unused dependency incorrectly,
2026-07-02T01:09:08.8973933Z        > you can add the dependency to the list of dependencies to ignore in the
2026-07-02T01:09:08.8975427Z        > `[package.metadata.cargo-machete]` section of the appropriate Cargo.toml.
2026-07-02T01:09:08.8976403Z        > For example:
2026-07-02T01:09:08.8976991Z        >
2026-07-02T01:09:08.8977600Z        > [package.metadata.cargo-machete]
2026-07-02T01:09:08.8978346Z        > ignored = ["prost"]
2026-07-02T01:09:08.8978983Z        >
2026-07-02T01:09:08.8980048Z        > You can also try running it with the `--with-metadata` flag for better accuracy,
2026-07-02T01:09:08.8981355Z        > though this may modify your Cargo.lock files.
2026-07-02T01:09:08.8982093Z        >
2026-07-02T01:09:08.8982643Z        > Done!
2026-07-02T01:09:08.8983224Z        For full logs, run:
2026-07-02T01:09:08.8984304Z          nix log /nix/store/f0fhx35c3p329xwryaf4904ra9qgr95k-payjoin-workspace-machete-no-version.drv
2026-07-02T01:09:08.9034590Z error: Cannot build '/nix/store/iszn68brb8jdwnsp2d89b9zsal6q4bfw-maintenance.drv'.
2026-07-02T01:09:08.9035595Z        Reason: 1 dependency failed.
2026-07-02T01:09:08.9036175Z        Output paths:
2026-07-02T01:09:08.9037023Z          /nix/store/yfqyn9ld1y122149ahhzr68b0c8vnrsk-maintenance
2026-07-02T01:09:10.7786183Z ❌ git+file:///home/runner/work/rust-payjoin/rust-payjoin?shallow=1#checks.x86_64-linux.maintenance

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants